/*
 * cmdline_parser.cpp
 *
 *  Created on: 22 Feb 2012
 *      Author: simon
 */

#include "cmdline_parser.h"

//-------------------------------------------------------------------------//
// Constructor, initialise the variables_map object with default
// constructor, options_descriptor with the name "Options"
//-------------------------------------------------------------------------//
cmdline_parser::cmdline_parser(void) : vm(), od("Options")
{
	// Shorter alias for the boost::program_options namespace
	namespace po = boost::program_options;

	// Add two cmdline options
	// --help or -?
	// --input-file or -i
	od.add_options()
		("help,?", "produce help message")
		((INPUTFILE+",i").c_str(), po::value<std::string>(),
			"input PGM file name")
		((DARKENFILE+",d").c_str(), po::value<std::string>(),
			"output PGM for darkening")
		((DARKENAMOUNT+",D").c_str(), po::value<int>(),
			"amount of darkening")
		((LIGHTENFILE+",l").c_str(), po::value<std::string>(),
			"output PGM for lightening")
		((LIGHTENAMOUNT+",L").c_str(), po::value<int>(),
			"amount of lightening")
		((INVERTFILE+",I").c_str(), po::value<std::string>(),
			"output PGM for inverting");
};

//-------------------------------------------------------------------------//
// Process the cmdline
//-------------------------------------------------------------------------//
bool cmdline_parser::process_cmdline(int argc, char * argv[])
{
	// Shorter alias for the boost::program_options namespace
	namespace po = boost::program_options;

	// Clear the variable map
	vm.clear();

	// Parse the cmdline arguments defined by argc and argv,
	// looking for the options defined in the od variable,
	// and store them in the vm variable.
	po::store(po::parse_command_line(argc, argv, od), vm);
	po::notify(vm);

	// Count the number of darken parameters
	int darken_params =
		(vm.count(DARKENAMOUNT) > 0 ? 1 : 0) +
		(vm.count(DARKENFILE) > 0 ? 1 : 0);

	// Count the number of lighten parameters
	int lighten_params =
		(vm.count(LIGHTENAMOUNT) > 0 ? 1 : 0) +
		(vm.count(LIGHTENFILE) > 0 ? 1 : 0);

	bool success = true;

	if(darken_params == 1)
	{
		success = false;
		errors.push_back(
			DARKENAMOUNT + " and " + DARKENFILE + " must be specified together.");
	}

	if(lighten_params == 1)
	{
		success = false;
		errors.push_back(
			LIGHTENAMOUNT + " and " + LIGHTENFILE + " must be specified together.");
	}

	if(vm.count(INPUTFILE) == 0)
	{
		success = false;
		errors.push_back(
			INPUTFILE + " not specified.");
	}

	return success;
}

//-----------------------------------------------------------------------//
// Return the input PGM filename
//-------------------------------------------------------------------------//
std::string cmdline_parser::get_input_filename(void) const
{
	// Return whatever value is stored as a string
	return vm[INPUTFILE].as<std::string>();
}

//-----------------------------------------------------------------------//
// Return the lightening output PGM filename
//-------------------------------------------------------------------------//
std::string cmdline_parser::get_lighten_filename(void) const
{
	// Return whatever value is stored  as a string
	return vm[LIGHTENFILE].as<std::string>();
}

//-----------------------------------------------------------------------//
// Return the darkening output PGM filename
//-------------------------------------------------------------------------//
std::string cmdline_parser::get_darken_filename(void) const
{
	// Return whatever value is stored as a string
	return vm[DARKENFILE].as<std::string>();
}

//-----------------------------------------------------------------------//
// Return the invert output PGM filename
//-------------------------------------------------------------------------//
std::string cmdline_parser::get_invert_filename(void) const
{
	return vm[INVERTFILE].as<std::string>();
}

//-------------------------------------------------------------------------//
// Get the lighten amount
//-------------------------------------------------------------------------//
int cmdline_parser::get_lighten_amount(void)
	{ return vm[LIGHTENAMOUNT].as<int>(); }

//-------------------------------------------------------------------------//
// Get the darken amount
//-------------------------------------------------------------------------//
int cmdline_parser::get_darken_amount(void)
	{ return vm[DARKENAMOUNT].as<int>(); }

//-------------------------------------------------------------------------//
// Should we lighten?
//-------------------------------------------------------------------------//
bool cmdline_parser::should_lighten(void)
	{ return vm.count(LIGHTENFILE) > 0; }
//-------------------------------------------------------------------------//
// Should we darken?
//-------------------------------------------------------------------------//
bool cmdline_parser::should_darken(void)
	{ return vm.count(DARKENFILE) > 0; }
//-------------------------------------------------------------------------//
// Should we invert?
//-------------------------------------------------------------------------//
bool cmdline_parser::should_invert(void)
	{ return vm.count(INVERTFILE) > 0; }

//-----------------------------------------------------------------------//
// Should we print cmdline help?
//-------------------------------------------------------------------------//
bool cmdline_parser::should_print_help(void) const
{
	// Are there instances of the help option stored in the variable map
	return vm.count("help") > 0;
}

//-------------------------------------------------------------------------//
// Print out the options_descriptor to the supplied output stream
//-------------------------------------------------------------------------//
void cmdline_parser::print_help(std::ostream & out) const
{
	out << od;
}

//-------------------------------------------------------------------------//
// Print out the options_descriptor to the supplied output stream
//-------------------------------------------------------------------------//
void cmdline_parser::print_errors(std::ostream & out) const
{
	std::cerr << "Error processing command line arguments:" << std::endl;
	std::copy(errors.begin(), errors.end(),
		std::ostream_iterator<std::string>(out, "\n"));
}

// Definition of static strings in the class
const std::string cmdline_parser::INPUTFILE = "input-file";
const std::string cmdline_parser::DARKENFILE = "darken-file";
const std::string cmdline_parser::DARKENAMOUNT = "darken-amount";
const std::string cmdline_parser::LIGHTENFILE = "lighten-file";
const std::string cmdline_parser::LIGHTENAMOUNT = "lighten-amount";
const std::string cmdline_parser::INVERTFILE = "invert-file";
